#include "unititemmodel.h"

#include "other/rosterelements.h"

#include <QDebug>

UnitItemModelItem::UnitItemModelItem(const QString& _key, float _cost, int _number, yALB_AbstractTreeItem *parent) :
    key(_key), cost(_cost), number(_number), yALB_AbstractTreeItem(parent)
{

}

UnitItemModelItem* UnitItemModelItem::parent() const {
    return dynamic_cast<UnitItemModelItem*>(yALB_AbstractTreeItem::parent());
}

UnitItemModelItem* UnitItemModelItem::child(int i) const {
    return static_cast<UnitItemModelItem*>(yALB_AbstractTreeItem::child(i));
}

UnitItemModel::UnitItemModel(const DualCollection<GameItem> *items, const DualCollection<GameCategory> *categories,
                             QObject *parent) :
    _items(items), _categories(categories), yALB_AbstractTreeModel(new yALB_AbstractTreeItem(NULL), parent)
{
    Q_ASSERT(items && categories);
}

UnitItemModel::~UnitItemModel() {
    delete rootItem;
}

QVariant UnitItemModel::data(const QModelIndex &index, int role) const {
    if(!index.isValid())
        return QVariant();

    UnitItemModelItem *item = static_cast<UnitItemModelItem*>(index.internalPointer());

    if(role == Qt::UserRole)
        return item->key;

    if(role != Qt::DisplayRole)
        return QVariant();

    if(!item->parent()) { // Category
        if(index.column() != NameColumn)
            return QVariant();
        if(item->key.isEmpty())
            return tr("Unclassified");
        else
            return _categories->getRealElement(item->key)->getName();
    } else { // Item
        switch(index.column()) {
        case NameColumn:
            return _items->getRealElement(item->key)->getName();
        case NumberColumn:
            return item->number;
        case CostColumn:
            return item->cost * item->number;
        }
    }

    return QVariant();
}

QVariant UnitItemModel::headerData(int section, Qt::Orientation orientation,
                                      int role) const {
    if(orientation != Qt::Horizontal || role != Qt::DisplayRole)
        return QVariant();
    switch(section) {
    case NameColumn:
        return tr("Item name");
    case NumberColumn:
        return tr("#");
    case CostColumn:
        return tr("Cost");
    default:
        return QVariant();
    }
}

int UnitItemModel::columnCount(const QModelIndex &parent) const {
    Q_UNUSED(parent)
    return ColumnNumber;
}

void UnitItemModel::setSource(const RosterUnit *unit) {
    // Clear current list
    if(rootItem->childCount() > 0) {
        beginRemoveRows(QModelIndex(), 0, rootItem->childCount()-1);
        rootItem->clearChildren();
        endRemoveRows();
    }
    categoryIndex.clear();
    itemIndex.clear();
    currentUnit = unit;
    if(unit) {
        UnitItems_t itemsInUnit(unit->getItemsInUnit());
        for(UnitItems_t::const_iterator i = itemsInUnit.constBegin();
            i != itemsInUnit.constEnd(); ++i) {
            addItemRow(i.key(), i.value());
        }
    }
}

void UnitItemModel::buildCategoryIndex() {
    categoryItems.clear();

    // Fill categoryItems with the item keys for each category

    QStringList keys(_items->keys());
    for(int i = 0; i<keys.size(); ++i) {
        categoryItems[_items->getRealElement(keys.at(i))->category] << keys.at(i);
    }
}

void UnitItemModel::updateDataForKey(const QString& key) {
    if(currentUnit == NULL)
        return;
    UnitItemModelItem *row = itemIndex.value(key, NULL);
    uint number = currentUnit->getItemsInUnit().value(key, 0);
    if(number > 0) {
        if(row) {
            row->number = number;
            emit dataChanged(index(row,0), index(row,ColumnNumber));
        } else {
            addItemRow(key, number);
        }
    } else if(row) {
        if(row->parent()->childCount() > 1) {
            int i = row->row();
            beginRemoveRows(index(row->parent(),0), i, i);
            delete row;
        } else {
            int i = row->parent()->row();
            beginRemoveRows(QModelIndex(), i,i);
            categoryIndex.remove(row->parent()->key);
            delete row->parent();
        }
        itemIndex.remove(key);
        endRemoveRows();
    }
}

void UnitItemModel::addItemRow(const QString& key, uint number) {
#ifdef EXTRA_CHECKS
            if(!_items->contains(key))
                return;
#endif
            GameItem *item = _items->getRealElement(key);
            if(number <= 0)
                return;

#ifdef EXTRA_CHECKS
            QString category = _categories->contains(item->category) ? item->category : "";
#else
            QString category = item->category;
#endif
            UnitItemModelItem *parent = categoryIndex.value(category);

            if(parent == NULL) {
                int parentIndex = rootItem->childCount();
                beginInsertRows(QModelIndex(), parentIndex, parentIndex);
                parent = new UnitItemModelItem(category,0,0, rootItem);
                categoryIndex.insert(category, parent);
                endInsertRows();
            }

            int row = parent->childCount();
            beginInsertRows(index(parent, 0), row, row);
            itemIndex[key] = new UnitItemModelItem(key, item->getCost(), number, parent);
            endInsertRows();
}

QString UnitItemModel::getKeyFromIndex(const QModelIndex& index) const {
    if(!index.isValid())
        return QString();
    UnitItemModelItem *item = static_cast<UnitItemModelItem*>(index.internalPointer());
    return item->key;
}
